home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Utilities / Interfaces / Except.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  11.3 KB  |  421 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Except.h
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Owned by:    Ted Jucevic
  7.  
  8.     Copyright:    © 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>      3/3/96    TJ        Added global gVolatile to help make
  13.                                     ODVolatile realy volatile.
  14.  
  15.     To Do:
  16. */
  17.  
  18. /*
  19.     File:        Except.h
  20.  
  21.     Contains:    Exception handling macros
  22.  
  23.     Owned by:    Jens Alfke
  24.  
  25.     Copyright:    © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  26.  
  27. */
  28.  
  29.  
  30. /*
  31.     THEORY OF OPERATION
  32.     
  33.     This is a catch/throw based exception handling package which models
  34.     much of the behavior of native C++ exception handling. (Its macros can
  35.     be redefined to use native exceptions if your compiler supports them.)
  36.     
  37.     Reading this header is not recommended for the faint of heart! Here be
  38.     gnarly macros, setjmp fu, and tangled #ifdefs.
  39.     Please see the recipe document "Using Exceptions" for details presented
  40.     in a human-readable fashion.
  41.     
  42.     If the symbol _NATIVE_EXCEPTIONS_ is predefined, native C++ exception
  43.     handling will be used.
  44.     If the symbol _ASM_XTRY_ is predefined, a special assembly-coded
  45.     version of _xTry will be called, which makes the calling code for TRY
  46.     shorter and slightly faster. (This feature still in progress...)
  47. */
  48.  
  49. #ifndef _EXCEPT_
  50. #define _EXCEPT_
  51.  
  52. #ifndef _ODTYPES_
  53. #include "ODTypes.h"
  54. #endif
  55.  
  56. #ifndef _ERRORDEF_
  57.     #ifdef __cplusplus
  58.     #include "ErrorDef.xh"    // Clients probably need the error codes as well
  59.     #else
  60.     #include "ErrorDef.h"
  61.     #endif
  62. #endif
  63.  
  64. #ifndef __SETJMP__
  65. #include <setjmp.h>
  66. #endif
  67.  
  68. #ifdef __LIBRARYMANAGER__
  69. #error "Please don't include both Except.h and LibraryManager.h"
  70. #endif
  71.  
  72.  
  73. #ifdef _OD_IMPL_SHARE_UTILS_
  74. #pragma import on
  75. #endif
  76.  
  77. #ifdef __cplusplus
  78. extern "C" {
  79. #endif
  80.  
  81.  
  82. //=====================================================================================
  83. // ODVolatile
  84. //=====================================================================================
  85.  
  86. // Any variable or parameter that is modified in a TRY block and used in the
  87. // CATCH block must be declared as volatile or it may have an incorrect value
  88. // in the CATCH block.
  89. // Since not all compilers support the 'volatile' keyword, use this instead;
  90.  
  91. extern void* gVolatile;
  92.  
  93. #ifndef _NATIVE_EXCEPTIONS_
  94. #define ODVolatile(x)    (gVolatile = &x)
  95. #else
  96. #define ODVolatile(x)    /*no need for this with native exceptions*/
  97. #endif
  98.  
  99. //=====================================================================================
  100. // Exception Handling Macros (native C++ exceptions)
  101. //=====================================================================================
  102.  
  103. #ifdef _NATIVE_EXCEPTIONS_
  104.  
  105. #define ErrorCode()                (_exception.error)
  106. #define ErrorMessage()            (_exception.message)
  107. #define SetErrorCode(ERR)        (_exception.error=(ERR))
  108. #define SetErrorMessage(MSG)    (strcpy(_exception.error,(MSG))
  109.  
  110. #define TRY                                                    \
  111.                 try {
  112.  
  113. #define CATCH_ALL                                            \
  114.                 } catch(ODException _exception) {
  115.  
  116. #define RERAISE                                                \
  117.                 throw
  118.  
  119. #define SET_SOM_EXCEPTION(EV)                                \
  120.                 ODSetSOMException(EV,_exception)
  121.  
  122. void _xSetSOMException(Environment*,ODException&);
  123.  
  124. #define ENDTRY                                                \
  125.                 }
  126.  
  127. /* CATCH( ) will not work with native exceptions. Don't use it! */
  128.  
  129.  
  130. //=====================================================================================
  131. // Exception Handling Macros (emulated)
  132. //=====================================================================================
  133.  
  134. #else /*not _NATIVE_EXCEPTIONS*/
  135.  
  136. #define ErrorCode()                 (_except.fError)
  137. #define ErrorMessage()                (_except.fODException ?_except.fODException->message :kODNULL)
  138. #define SetErrorCode(ERR)            (_xSetErrorCode(&_except,(ERR)))
  139. #define SetErrorMessage(MSG)        (_xSetErrorMessage(&_except,(MSG))
  140.  
  141. #ifndef _ASM_XTRY_
  142.     #define _setjmp_xTry(EX)        setjmp(*_xTry(EX))
  143.     #define _setjmp_xTryEv(EX,EV)    setjmp(*_xTryEv(EX,EV))
  144. #endif
  145.  
  146. #define TRY                                                 \
  147.     {                                                        \
  148.         ODExceptionFrame _except;                            \
  149.         ODVolatile(_except);                                \
  150.         if (_setjmp_xTry(&_except) == 0)                    \
  151.         {
  152.         
  153. #define CATCH_ALL                                            \
  154.         }                                                    \
  155.         if (_except.fError)                                    \
  156.         { 
  157.         
  158.         
  159. #define RERAISE                                                \
  160.         _xReraise(&_except)
  161.  
  162. #define SET_SOM_EXCEPTION(EV)                                \
  163.         _xSetSOMException(EV,&_except)
  164.         
  165. #ifdef __cplusplus    
  166. #define ENDTRY                                                \
  167.         }                                                    \
  168.     }
  169. #else // C version:
  170. #define ENDTRY                                                \
  171.         }                                                    \
  172.         _xPop(&_except);                                    \
  173.     }
  174. #endif
  175.  
  176. // CATCH( ) is not compatible with native C++ exceptions.
  177. // Its use is discouraged.
  178. #define CATCH(e)                                            \
  179.         }                                                     \
  180.         if (_except.fError==(e)) { 
  181.         
  182.         
  183. #endif /*_NATIVE_EXCEPTIONS*/
  184.  
  185. //=====================================================================================
  186. // Raising Exceptions
  187. //=====================================================================================
  188.  
  189. void THROW(ODError error);
  190. void THROW_IF_ERROR(ODError error);
  191. void THROW_IF_NULL(void* value);
  192.  
  193. // Optional message parameters (ignored in nondebug build):
  194. #if ODDebug
  195. void THROW_IF_ERROR_M(ODError error, const char* msg);
  196. void THROW_M(ODError error, const char* msg);
  197. void THROW_IF_NULL_M(void* value, const char* msg);
  198. #else
  199. #define THROW_IF_ERROR_M(ERR,MSG)    THROW_IF_ERROR(ERR)
  200. #define THROW_M(ERR,MSG)            THROW(ERR)
  201. #define THROW_IF_NULL_M(ERR,MSG)    THROW_IF_NULL(ERR)
  202. #endif
  203.  
  204. #ifdef __cplusplus
  205. }
  206. // Overloaded C++ equivalents:
  207. inline void THROW_IF_ERROR(ODError error, const char* msg)
  208.                             {THROW_IF_ERROR_M(error,msg);}
  209. inline void THROW(ODError error, const char* msg)
  210.                             {THROW_M(error,msg);}
  211. inline void THROW_IF_NULL(void* value, const char* msg)
  212.                             {THROW_IF_NULL_M(value,msg);}
  213. inline void THROW_IF_NULL(void* value, ODError error)
  214.                             {if ( value == kODNULL ) THROW(error);}
  215. extern "C" {
  216. #endif
  217.  
  218. // Call BreakOnThrow(TRUE) to break into the debugger whenever THROW is called.
  219. // (The call returns the previous value of the setting.)
  220. ODBoolean BreakOnThrow( ODBoolean brk );
  221.  
  222.  
  223. //=====================================================================================
  224. // SOM Exception Utilities
  225. //=====================================================================================
  226.  
  227. // This modified TRY block should be used in SOM methods. It's just like a
  228. // regular TRY...CATCH_ALL...ENDTRY except that the exception code will be
  229. // stored in the Environment. Needless to say you should _not_ reraise!
  230. // You should also not make any SOM calls after the SOM_ENDTRY, nor declare any
  231. // Destructo objects before the SOM_TRY.
  232.  
  233. #ifdef _NATIVE_EXCEPTIONS_
  234.  
  235. #define SOM_TRY                                                 \
  236.             TRY
  237.             
  238. #define SOM_CATCH_ALL                                            \
  239.             CATCH_ALL {                                            \
  240.                 
  241. #define SOM_ENDTRY                                                \
  242.             } ODSetSOMException(ev,_exception);                    \
  243.             ENDTRY
  244.             
  245. #else /*not _NATIVE_EXCEPTIONS_*/
  246.  
  247. #define SOM_TRY                                                 \
  248.         {                                                        \
  249.             ODExceptionFrame _except;                            \
  250.             ODVolatile(_except);                                \
  251.             if (_setjmp_xTryEv(&_except,ev) == 0)                \
  252.             {
  253.  
  254. #define SOM_CATCH_ALL                                            \
  255.             CATCH_ALL
  256. #define SOM_ENDTRY                                                \
  257.             ENDTRY
  258.  
  259. #endif /*_NATIVE_EXCEPTIONS_*/
  260.  
  261.  
  262. // ODSetSOMException stores an OD error code in the environment.
  263. // ODGetSOMException returns the OD error code (if any) from an environment.
  264.  
  265. #ifdef __cplusplus
  266. void    ODSetSOMException( Environment*, ODError, const char *msg =kODNULL );
  267. #else
  268. void    ODSetSOMException( Environment*, ODError, const char *msg );
  269. #endif
  270.  
  271. #ifdef _NATIVE_EXCEPTIONS_
  272. } // end extern C
  273. void    ODSetSOMException( Environment*, ODException& );
  274. extern "C" {
  275. #endif
  276.  
  277. ODError    ODGetSOMException( Environment *ev );
  278.  
  279. // CHECK_ENV throws an exception if the environment indicates an error.
  280.  
  281. void    CHECK_ENV( Environment* );
  282.  
  283. // SOMCHKEXCEPT is a macro that is called in a .xh file if the ev variable
  284. // indicates an exception is set.
  285. #define SOMCHKEXCEPT {CHECK_ENV(ev);}
  286.  
  287.  
  288. //=====================================================================================
  289. // Obsolete Exception Utilities
  290. //=====================================================================================
  291.  
  292. /*  FN_CATCH and SOM_CATCH are discouraged (not compatible with native C++
  293.     exceptions) but still implemented for the time being to give people time
  294.     to convert their code. */
  295.  
  296. #if defined(__MWERKS__) || defined(__SC__)
  297.     extern void FN_CATCH_DIDNT_RETURN( );
  298.     /* This function is purposely declared but never defined. Due to the setup of
  299.        the for loop in FN_CATCH and SOM_CATCH, a failure to end the block with a
  300.        return statement will cause the call to FN_CATCH_DIDNT_RETURN not to be
  301.        dead stripped, resulting in a link error. This will help catch this nasty
  302.        coding error. */
  303. #else
  304.     // Other compilers may not dead-strip properly.
  305.     #define FN_CATCH_DIDNT_RETURN() /**/
  306. #endif
  307.  
  308. #define FN_CATCH                                            \
  309.         ODExceptionFrame _except;                            \
  310.         ODVolatile(_except);                                \
  311.         if (_setjmp_xTry(&_except) != 0)                    \
  312.             for( ; true; FN_CATCH_DIDNT_RETURN() )
  313.  
  314. #define SOM_CATCH                                            \
  315.         ODExceptionFrame _except;                            \
  316.         ODVolatile(_except);                                \
  317.         if (_setjmp_xTryEv(&_except,ev) != 0)                \
  318.             for( ; true; FN_CATCH_DIDNT_RETURN() )
  319.  
  320.  
  321. //=====================================================================================
  322. // Finally, the Exception Handler (ODExceptionFrame struct)
  323. //=====================================================================================
  324.  
  325.  
  326. #ifndef _NATIVE_EXCEPTIONS_
  327.  
  328. #ifdef __cplusplus
  329. class Destructo;    // forward declarations for use below
  330. struct ODExceptionFrame;
  331. void _xPop(ODExceptionFrame*);
  332. }    // end of extern "C" block
  333. #else
  334. typedef struct ODExceptionFrame ODExceptionFrame;
  335. typedef struct Destructo Destructo;        // Not used in C but must declare anyway
  336. #endif
  337.  
  338. struct ODExceptionFrame
  339. {
  340.     ODExceptionFrame*    fPrev;
  341.     ODException*        fODException;
  342.     ODError                fError;
  343.     Environment*        fEv;
  344.     Destructo*            fDestructoList;
  345.     jmp_buf                fBuffer;
  346.     // If you change the size of this struct you _must_ update Except.s and Except.a
  347.     // accordingly!
  348. #ifdef __cplusplus
  349.     void Throw( ODError err, const char* msg, ODException *x =kODNULL );
  350.     inline ~ODExceptionFrame( )    {_xPop(this);}
  351. #endif
  352. };
  353.  
  354. #ifdef __cplusplus
  355. extern "C" {
  356. #endif
  357.  
  358. typedef struct ODExceptionFrame ODExceptionFrame;
  359.  
  360. #ifdef _ASM_XTRY_
  361.     int _setjmp_xTry( ODExceptionFrame* );
  362.     int _setjmp_xTryEv( ODExceptionFrame*, Environment* );
  363. #else
  364.     jmp_buf* _xTry( ODExceptionFrame* );
  365.     jmp_buf* _xTryEv( ODExceptionFrame*, Environment* );
  366. #endif
  367.  
  368. void _xReraise( ODExceptionFrame* );
  369. void _xSetSOMException(Environment*,ODExceptionFrame*);
  370. void _xPop( ODExceptionFrame* );
  371. void _xSetErrorCode( ODExceptionFrame*, ODError );
  372. void _xSetErrorMessage( ODExceptionFrame*, const char* );
  373.  
  374. #endif /*_NATIVE_EXCEPTIONS_*/
  375.  
  376.  
  377. #ifdef __cplusplus
  378. }    // end of extern "C" block
  379. #endif
  380.  
  381.  
  382. //=====================================================================================
  383. // Destructo, a C++ base class for auto-destruct objects
  384. //=====================================================================================
  385.  
  386. #ifdef __cplusplus
  387.  
  388. class Destructo
  389. {
  390. #ifndef _NATIVE_EXCEPTIONS_
  391. protected:
  392.     Destructo( );
  393.     
  394. public:
  395.     virtual ~Destructo( );
  396.     
  397. private:
  398.     Destructo* EmergencyDestruct( );
  399.     Destructo *fPrevDestructo;
  400.     friend class ODExceptionFrame;
  401.  
  402. #endif /*_NATIVE_EXCEPTIONS_*/
  403.     static void* operator new( size_t );    // Make it illegal to allocate on heap
  404.                                             // In future could use alloca??
  405.                                             
  406.     private: // disallow these:
  407.     Destructo(const Destructo& );
  408.     void operator=(const Destructo& );
  409.     // Bitwise assigning one destructo to another smashes
  410.     // fPrevDestructo with potentially unpleasant effects.
  411. };
  412.  
  413. #endif /*__cplusplus*/
  414.  
  415. #ifdef _OD_IMPL_SHARE_UTILS_
  416. #pragma import off
  417. #endif
  418.  
  419.  
  420. #endif // _EXCEPT_
  421.